package com.ccys.db.rely.service.impl;

import com.ccys.db.mapper.CommonMapper;
import com.ccys.common.util.Kit;
import com.ccys.db.rely.service.BaseService;
import org.springframework.beans.factory.annotation.Autowired;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import javax.persistence.Transient;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 调用通用mapper实现单表操作
 */
public abstract class BaseServiceImpl<T> implements BaseService<T> {

    @Autowired
    private Mapper<T> mapper;
	@Autowired
	private CommonMapper commonMapper;

    /**
	 * 保存实体
	 * @param entity
	 * @return
	 */
	@Override
	public int saveEntity(T entity){
		return this.mapper.insertSelective(entity);
	}

	/**
	 * 简单实体新增修改
	 * @param entity
	 * @return
	 */
	@Override
	public int insertOrUpdate(T entity){
		if (!Kit.paramValid(entity.getClass(),entity, "id")) {
			return saveEntity(entity);
		} else {
			return updateEntityById(entity);
		}
	}

	/**
	 * 根据ID删除实体
	 * @param id
	 * @return
	 */
	@Override
	public int deleteById(String id) {
        return this.mapper.deleteByPrimaryKey(id);
	}
	
	/**
	 * 根据条件删除实体
	 * @param entityClass	实体的class
	 * @param whereList		注：条件字段用表字段，非实体属性名
	 * @return
	 */
	@Override
	public int deleteByLimit(Class<?> entityClass, List<String> whereList){
		return this.mapper.deleteByExample(this.packagingExample(entityClass, whereList,null));
	}

	/**
	 * 根据ID修改实体中【非空】的字段
	 * @param entity
	 * @return
	 */
	@Override
	public int updateEntityById(T entity){
		return this.mapper.updateByPrimaryKeySelective(entity);
	}
	
	/**
	 * 根据条件修改实体中【非空】的字段
	 * @param entity
	 * @param whereList		注：条件字段用表字段，非实体属性名
	 * @return
	 */
	@Override
	public int updateByEntity(T entity, List<String> whereList){
		return this.mapper.updateByExampleSelective(entity, this.packagingExample(entity.getClass(), whereList,null));
	}
	
	/**
	 * 根据ID修改实体中【所有】的字段
	 * @param entity
	 * @return
	 */
	@Override
	public int updateAll(T entity) {
		return this.mapper.updateByPrimaryKey(entity);
	}
	
	/**
	 * 根据ID查询单个实体
	 * @param id
	 * @return
	 */
	@Override
	public T findEntityById(String id){
		return this.mapper.selectByPrimaryKey(id);
	}
	
	/**
	 * 根据条件查询单个实体
	 * @param entityClass	实体的class
	 * @param whereList		注：条件字段用表字段，非实体属性名
	 * @return
	 */
	@Override
	public T findOneByLimit(Class<?> entityClass, List<String> whereList){
		List<T> list = this.findListByLimit(entityClass, whereList,null);
    	if(list.size() >= 1){
    		return list.get(0);
    	}
    	return null;
	}
	
	/**
	 * 根据条件获取多个实体
	 * @param entityClass		实体的class
	 * @param whereList			注：条件字段用表字段，非实体属性名
	 * @param orderByClause		排序字段	如："create_time desc"
	 * @return
	 */
	@Override
	public List<T> findListByLimit(Class<?> entityClass, List<String> whereList, String orderByClause){
		return this.mapper.selectByExample(this.packagingExample(entityClass, whereList,orderByClause));
	}
	
	 /**
     * 封装条件
     * @param entityClass
     * @param whereList
     * @return
     */
    private Example packagingExample(Class<?> entityClass,List<String> whereList,String orderByClause){
    	Example example = new Example(entityClass);
        Example.Criteria criteria = example.createCriteria();
         
    	if(whereList != null){
    		for(String where : whereList){
        		criteria.andCondition(where);
    		}
    	}
    	
    	if(orderByClause != null && !"".equals(orderByClause)){
    		example.setOrderByClause(orderByClause);
    	}
        
    	return example;
    }

	@Override
	public int insertAll(List<T> list,int split) {
		if (split == 0) {
			return 0;
		}
		int group = Math.round(list.size() / (float)split);
		int start;
		int end;
		int insert = 0;
		List<T> subList = null;
		for (int i = 0; i < group; i++) {
			start = i * 10;
			end = start + 10;
			if (i == group - 1) {
				end = list.size();
			}
			subList = list.subList(start, end);
			insert += this.insertAll(subList);
		}
		return insert;
	}

	@Override
	public int insertAll(List<T> list) {
		try {
			if (list == null || list.isEmpty()) {
				return 0;
			}
			Class<?> listClass = this.getClass();
			Type type = ((ParameterizedType) listClass.getGenericSuperclass()).getActualTypeArguments()[0];
			String typeName = type.getTypeName();
			Class<?> clazz = Class.forName(typeName);
			Class<?> superclass = clazz.getSuperclass();
			Field[] thisFields = clazz.getDeclaredFields();
			List<Field> fields = new ArrayList<>(Arrays.asList(thisFields));
			if (superclass != null) {
				Field[] superFields = superclass.getDeclaredFields();
				fields.addAll(Arrays.asList(superFields));
			}
			for (int i = 0; i < fields.size(); i++) {
				Field field = fields.get(i);
				if (field.isAnnotationPresent(Transient.class) || Modifier.isStatic(field.getModifiers())) {
					fields.remove(i);
					i--;
					continue;
				}
			}
			StringBuffer insertSql = new StringBuffer();
			insertSql.append("insert into ");
			insertSql.append("`"+Kit.className2TableName(clazz)+"` ");
			insertSql.append("(");
			//加入去重
			List<String> useColumnNames = new ArrayList<>();
			for (int i = 0; i < fields.size(); i++) {
				Field field = fields.get(i);
				String columnName = Kit.propertyName2ColumnName(field.getName());
				if (useColumnNames.contains(columnName)) {
					continue;
				}
				useColumnNames.add(columnName);
				insertSql.append("`"+columnName+"`");
				if (i != fields.size() - 1) {
					insertSql.append(",");
				}
			}
			insertSql.append(") ");
			// values
			insertSql.append("VALUES");
			SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			List<String> usePropertyNames = new ArrayList<>();
			for (int i = 0; i < list.size(); i++) {
				T data = list.get(i);
				insertSql.append("(");

				for (int j = 0; j < fields.size(); j++) {
					Field field = fields.get(j);
					if (usePropertyNames.contains(field.getName())) {
						continue;
					}
					usePropertyNames.add(field.getName());
					field.setAccessible(true);
					Object o = field.get(data);
					String value = "DEFAULT";

					if (o != null&& "java.util.Date".equals(field.getType().getName())) {
						value = format.format(((Date) o));
					} else if (o != null) {
						value = String.valueOf(o);
					}

					if (o != null) {
						insertSql.append("'");
						insertSql.append(value);
						insertSql.append("'");
					}else {
						insertSql.append(value);
					}

					if (j != fields.size() - 1) {
						insertSql.append(",");
					}
					field.setAccessible(false);
				}
				usePropertyNames.clear();
				insertSql.append(")");
				if (i < list.size() - 1) {
					insertSql.append(",");
				}
			}

			return commonMapper.doSql(insertSql.toString());
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
	}
}
